import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UserService } from '../../modules/user/user.service';

type JwtPayload = {
  sub: number;
  username: string;
};

@Injectable()
// PassportStrategy工厂函数会返回一个继承自原始Strategy的类
// 第二参数'auth'用于指定策略名称
export class JwtStrategy extends PassportStrategy(Strategy, 'auth') {
  constructor(private userService: UserService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // 从请求头的Authorization字段中提取JWT
      secretOrKey: process.env.JWT_SECRET ?? 'hyh501659423', // 密钥
      ignoreExpiration: false, // 忽略过期时间
      passReqToCallback: false, // 不传递请求对象到回调函数
    } as const);
  }
  /*
   * 当请求携带有效的JWT时，Passport的JWT策略会自动解析token
   * 验证签名和有效期后，会将解码后的payload传递给validate方法
   * validate方法返回的用户对象会被自动附加到请求对象上
   * */

  /*
   * 在NestJS的JWT策略中，当token本身失效（如过期或签名错误）时
   * 验证失败会发生在进入validate方法之前
   * 当 passReqToCallback 设置为 true 时，validate 方法应该接收请求对象作为第一个参数，payload 作为第二个参数
   * */
  async validate(payload: JwtPayload) {
    const user = await this.userService.findById(payload.sub);
    if (!user) {
      throw new UnauthorizedException('用户不存在或登录已过期');
    }
    return user;
  }
}
